package com.suxin.thread;

import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Tang
 * @classname ServiceThread
 * @description [  ]
 * @date 2022/11/8 10:50
 */
@Slf4j
public abstract class ServiceThread implements Runnable{

    private Thread thread;

    private final AtomicBoolean started = new AtomicBoolean(false);

    private final AtomicBoolean hasNotified = new AtomicBoolean(false);

    private final CountDownLatch2 downLatch = new CountDownLatch2(2);

    public ServiceThread() {
    }

    /**
     * getServiceName
     * @return
     */
    public abstract String getServiceName();

    /**
     * isDaemon
     * @return
     */
    public abstract boolean isDaemon();

    public void start() {
        log.info("Try to start service thread:{},started:{} lastThread:{}",getServiceName(),started.get(),thread);
        if (!started.compareAndSet(false, true)) {
            return;
        }
        this.thread = new Thread(this, getServiceName());
        this.thread.setDaemon(isDaemon());
        this.thread.start();
    }

    public void wakeUp() {
        if(hasNotified.compareAndSet(false, true)) {
            downLatch.countDown();
        }
    }

    public void waitForRunning(long interval) {
        if (hasNotified.compareAndSet(true, false)) {
            this.onWaitEnd();
            return;
        }
        downLatch.reset();
        try {
            downLatch.await(interval, TimeUnit.MICROSECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            hasNotified.set(false);
            this.onWaitEnd();
        }
    }

    protected void onWaitEnd() {

    }

    public void shutdown() {
        this.thread.interrupt();
    }

}
